﻿using Roton.Memory;
using Roton.ZZT;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Roton.Wrapper
{
    /// <summary>
    /// Adapts IState to a Segment object.
    /// </summary>
    class StateWrapper : IState
    {
        protected StateWrapperProperties properties;
        protected Segment segment;

        public StateWrapper(int offset, Segment segment, StateWrapperProperties properties)
        {
            this.segment = segment;
            properties.OffsetAboutShown += offset;
            properties.OffsetActIndex += offset;
            properties.OffsetAlertAmmo += offset;
            properties.OffsetAlertDark += offset;
            properties.OffsetAlertEnergy += offset;
            properties.OffsetAlertFake += offset;
            properties.OffsetAlertForest += offset;
            properties.OffsetAlertGem += offset;
            properties.OffsetAlertNoAmmo += offset;
            properties.OffsetAlertNoShoot += offset;
            properties.OffsetAlertNotDark += offset;
            properties.OffsetAlertNoTorch += offset;
            properties.OffsetAlertTorch += offset;
            properties.OffsetBoardCount += offset;
            properties.OffsetBorderTile += offset;
            properties.OffsetBreakGameLoop += offset;
            properties.OffsetCancelScroll += offset;
            properties.OffsetDefaultBoardName += offset;
            properties.OffsetDefaultSaveName += offset;
            properties.OffsetDefaultWorldName += offset;
            properties.OffsetEdgeTile += offset;
            properties.OffsetEditorMode += offset;
            properties.OffsetGameCycle += offset;
            properties.OffsetGameOver += offset;
            properties.OffsetGamePaused += offset;
            properties.OffsetGameQuiet += offset;
            properties.OffsetGameSpeed += offset;
            properties.OffsetGameWaitTime += offset;
            properties.OffsetInit += offset;
            properties.OffsetKeyArrow += offset;
            properties.OffsetKeyPressed += offset;
            properties.OffsetKeyShift += offset;
            properties.OffsetKeyVector += offset;
            properties.OffsetLineChars += offset;
            properties.OffsetMessage += offset;
            properties.OffsetOOPByte += offset;
            properties.OffsetOOPNumber += offset;
            properties.OffsetOOPWord += offset;
            properties.OffsetPlayerElement += offset;
            properties.OffsetQuitZZT += offset;
            properties.OffsetSoundBuffer += offset;
            properties.OffsetSoundPlaying += offset;
            properties.OffsetSoundPriority += offset;
            properties.OffsetSoundTicks += offset;
            properties.OffsetStarChars += offset;
            properties.OffsetStartBoard += offset;
            properties.OffsetThingCount += offset;
            properties.OffsetTransporterHChars += offset;
            properties.OffsetTransporterVChars += offset;
            properties.OffsetVector4 += offset;
            properties.OffsetVector8 += offset;
            properties.OffsetVisibleTileCount += offset;
            properties.OffsetWebChars += offset;
            properties.OffsetWorldFileName += offset;
            properties.OffsetWorldLoaded += offset;
            this.properties = properties;
        }

        public bool AboutShown
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAboutShown);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAboutShown, value);
            }
        }

        public int ActIndex
        {
            get
            {
                return segment.Read16(properties.OffsetActIndex);
            }
            set
            {
                segment.Write16(properties.OffsetActIndex, value);
            }
        }

        public bool AlertAmmo
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlertAmmo);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlertAmmo, value);
            }
        }

        public bool AlertDark
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlertDark);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlertDark, value);
            }
        }

        public bool AlertEnergy
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlertEnergy);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlertEnergy, value);
            }
        }

        public bool AlertFake
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlertFake);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlertFake, value);
            }
        }

        public bool AlertForest
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlertForest);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlertForest, value);
            }
        }

        public bool AlertGem
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlertGem);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlertGem, value);
            }
        }

        public bool AlertNoAmmo
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlertNoAmmo);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlertNoAmmo, value);
            }
        }

        public bool AlertNoShoot
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlertNoShoot);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlertNoShoot, value);
            }
        }

        public bool AlertNotDark
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlertNotDark);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlertNotDark, value);
            }
        }

        public bool AlertNoTorch
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlertNoTorch);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlertNoTorch, value);
            }
        }

        public bool AlertTorch
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetAlertTorch);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetAlertTorch, value);
            }
        }

        public int BoardCount
        {
            get
            {
                return segment.Read16(properties.OffsetBoardCount);
            }
            set
            {
                segment.Write16(properties.OffsetBoardCount, value);
            }
        }

        public int BorderColor
        {
            get
            {
                return segment.Read8(properties.OffsetBorderTile + 1);
            }
            set
            {
                segment.Write8(properties.OffsetBorderTile + 1, value);
            }
        }

        public int BorderID
        {
            get
            {
                return segment.Read8(properties.OffsetBorderTile);
            }
            set
            {
                segment.Write8(properties.OffsetBorderTile, value);
            }
        }

        public bool BreakGameLoop
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetBreakGameLoop);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetBreakGameLoop, value);
            }
        }

        public bool CancelScroll
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetCancelScroll);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetCancelScroll, value);
            }
        }

        public IString DefaultBoardName
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetDefaultBoardName, segment);
            }
        }

        public IString DefaultSaveName
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetDefaultSaveName, segment);
            }
        }

        public IString DefaultWorldName
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetDefaultWorldName, segment);
            }
        }

        public int EdgeColor
        {
            get
            {
                return segment.Read8(properties.OffsetEdgeTile + 1);
            }
            set
            {
                segment.Write8(properties.OffsetEdgeTile + 1, value);
            }
        }

        public int EdgeID
        {
            get
            {
                return segment.Read8(properties.OffsetEdgeTile);
            }
            set
            {
                segment.Write8(properties.OffsetEdgeTile, value);
            }
        }

        public bool EditorMode
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetEditorMode);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetEditorMode, value);
            }
        }

        public int GameCycle
        {
            get
            {
                return segment.Read16(properties.OffsetGameCycle);
            }
            set
            {
                segment.Write16(properties.OffsetGameCycle, value);
            }
        }

        public bool GameOver
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetGameOver);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetGameOver, value);
            }
        }

        public bool GamePaused
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetGamePaused);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetGamePaused, value);
            }
        }

        public bool GameQuiet
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetGameQuiet);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetGameQuiet, value);
            }
        }

        public int GameSpeed
        {
            get
            {
                return segment.Read8(properties.OffsetGameSpeed);
            }
            set
            {
                segment.Write8(properties.OffsetGameSpeed, value);
            }
        }

        public int GameWaitTime
        {
            get
            {
                return segment.Read16(properties.OffsetGameWaitTime);
            }
            set
            {
                segment.Write16(properties.OffsetGameWaitTime, value);
            }
        }

        public bool Init
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetInit);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetInit, value);
            }
        }

        public bool KeyArrow
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetKeyArrow);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetKeyArrow, value);
            }
        }

        public byte KeyPressed
        {
            get
            {
                return (byte)segment.Read8(properties.OffsetKeyPressed);
            }
            set
            {
                segment.Write8(properties.OffsetKeyPressed, value);
            }
        }

        public bool KeyShift
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetKeyShift);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetKeyShift, value);
            }
        }

        public IVector KeyVector
        {
            get 
            {
                return new VectorWrapper(properties.OffsetKeyVector, segment);
            }
        }

        public int KeyVectorX
        {
            get
            {
                return segment.Read8(properties.OffsetKeyVector);
            }
            set
            {
                segment.Write8(properties.OffsetKeyVector, value);
            }
        }

        public int KeyVectorY
        {
            get
            {
                return segment.Read8(properties.OffsetKeyVector + 1);
            }
            set
            {
                segment.Write8(properties.OffsetKeyVector + 1, value);
            }
        }

        public IString LineChars
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetLineChars, segment);
            }
        }

        public IString Message
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetMessage, segment);
            }
        }

        public byte OOPByte
        {
            get
            {
                return (byte)segment.Read8(properties.OffsetOOPByte);
            }
            set
            {
                segment.Write8(properties.OffsetOOPByte, value);
            }
        }

        public int OOPNumber
        {
            get
            {
                return segment.Read16(properties.OffsetOOPNumber);
            }
            set
            {
                segment.Write16(properties.OffsetOOPNumber, value);
            }
        }

        public IString OOPWord
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetOOPWord, segment);
            }
        }

        public int PlayerElement
        {
            get
            {
                return segment.Read8(properties.OffsetPlayerElement);
            }
            set
            {
                segment.Write8(properties.OffsetPlayerElement, value);
            }
        }

        public bool QuitZZT
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetQuitZZT);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetQuitZZT, value);
            }
        }

        public IString SoundBuffer
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetSoundBuffer, segment);
            }
        }

        public bool SoundPlaying
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetSoundPlaying);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetSoundPlaying, value);
            }
        }

        public int SoundPriority
        {
            get
            {
                return segment.Read16(properties.OffsetSoundPriority);
            }
            set
            {
                segment.Write16(properties.OffsetSoundPriority, value);
            }
        }

        public int SoundTicks
        {
            get
            {
                return segment.Read8(properties.OffsetSoundTicks);
            }
            set
            {
                segment.Write8(properties.OffsetSoundTicks, value);
            }
        }

        public IString StarChars
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetStarChars, segment);
            }
        }

        public int StartBoard
        {
            get
            {
                return segment.Read16(properties.OffsetStartBoard);
            }
            set
            {
                segment.Write16(properties.OffsetStartBoard, value);
            }
        }

        public int ThingCount
        {
            get
            {
                return segment.Read16(properties.OffsetThingCount);
            }
            set
            {
                segment.Write16(properties.OffsetThingCount, value);
            }
        }

        public IString TransporterHChars
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetTransporterHChars, segment);
            }
        }

        public IString TransporterVChars
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetTransporterVChars, segment);
            }
        }

        public int Vector4X(int index)
        {
            return segment.Read16(properties.OffsetVector4 + (index * 2));
        }

        public int Vector4Y(int index)
        {
            return segment.Read16(properties.OffsetVector4 + 8 + (index * 2));
        }

        public int Vector8X(int index)
        {
            return segment.Read16(properties.OffsetVector8 + (index * 2));
        }

        public int Vector8Y(int index)
        {
            return segment.Read16(properties.OffsetVector8 + 16 + (index * 2));
        }

        public int VisibleTileCount
        {
            get
            {
                return segment.Read16(properties.OffsetVisibleTileCount);
            }
            set
            {
                segment.Write16(properties.OffsetVisibleTileCount, value);
            }
        }

        public IString WebChars
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetWebChars, segment);
            }
        }

        public IString WorldFileName
        {
            get
            {
                return new ByteStringWrapper(properties.OffsetWorldFileName, segment);
            }
        }

        public bool WorldLoaded
        {
            get
            {
                return segment.ReadBoolean(properties.OffsetWorldLoaded);
            }
            set
            {
                segment.WriteBoolean(properties.OffsetWorldLoaded, value);
            }
        }
    }

    struct StateWrapperProperties
    {
        public int OffsetAboutShown;
        public int OffsetActIndex;
        public int OffsetAlertAmmo;
        public int OffsetAlertDark;
        public int OffsetAlertEnergy;
        public int OffsetAlertFake;
        public int OffsetAlertForest;
        public int OffsetAlertGem;
        public int OffsetAlertNoAmmo;
        public int OffsetAlertNoShoot;
        public int OffsetAlertNotDark;
        public int OffsetAlertNoTorch;
        public int OffsetAlertTorch;
        public int OffsetBoardCount;
        public int OffsetBorderTile;
        public int OffsetBreakGameLoop;
        public int OffsetCancelScroll;
        public int OffsetDefaultBoardName;
        public int OffsetDefaultSaveName;
        public int OffsetDefaultWorldName;
        public int OffsetEdgeTile;
        public int OffsetEditorMode;
        public int OffsetGameCycle;
        public int OffsetGameOver;
        public int OffsetGamePaused;
        public int OffsetGameQuiet;
        public int OffsetGameSpeed;
        public int OffsetGameWaitTime;
        public int OffsetInit;
        public int OffsetKeyArrow;
        public int OffsetKeyPressed;
        public int OffsetKeyShift;
        public int OffsetKeyVector;
        public int OffsetLineChars;
        public int OffsetMessage;
        public int OffsetOOPByte;
        public int OffsetOOPNumber;
        public int OffsetOOPWord;
        public int OffsetPlayerElement;
        public int OffsetQuitZZT;
        public int OffsetSoundBuffer;
        public int OffsetSoundPlaying;
        public int OffsetSoundPriority;
        public int OffsetSoundTicks;
        public int OffsetStarChars;
        public int OffsetStartBoard;
        public int OffsetThingCount;
        public int OffsetTransporterHChars;
        public int OffsetTransporterVChars;
        public int OffsetVector4;
        public int OffsetVector8;
        public int OffsetVisibleTileCount;
        public int OffsetWebChars;
        public int OffsetWorldFileName;
        public int OffsetWorldLoaded;

    }
}
